package com.lq.memo.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lq.memo.service.redis.RedisService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @ClassName LettuceRedisConfigure
 * @Description
 * @Author LQ
 * @Date 2021/11/22 0:29
 * @Version 1.0
 */
public class LettuceRedisConfigure {
    /**
     * 自定义一个泛型为<String,Object>的RedisTemplate
     * 指定key序列化策略为StringRedisSerializer
     * 指定value序列化策略为Jackson2JsonRedisSerializer,内部采用ObjectMapper(Spring Boot中的JSON技术)来序列化对象
     *
     *@ConditionalOnClass (RedisOperations.class)表示只有当项目里存在RedisOperations类的时候
     * （即引入了spring-boot-starter-data-redis依赖的时候），我们自定义的RedisTemplateBean才会被注册到IOC容器中
     *
     * @param factory
     * @return
     */
    @Bean
    @ConditionalOnClass(RedisOperations.class)
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用Jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value也采用jackson的序列化方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

    /**
     * 将RedisService注册到IOC容器中,前提是IOC容器中存在名称为redisTemplate的Bean
     *
     * @ConditionalOnBean 当容器中存在指定的bean的时候才注册到容器中(name = "redisTemplate")
     *
     * @return
     */
    @Bean
    @ConditionalOnBean(name = "redisTemplate")
    public RedisService redisService(){
        return new RedisService();
    }

}
